package com.infodeli.user.login.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.infodeli.common.enums.LocalAuthEnum;
import com.infodeli.common.exception.ExceptionEnum;
import com.infodeli.common.exception.ServiceException;
import com.infodeli.common.utils.ComTool;
import com.infodeli.common.utils.ServiceExceptionUtils;
import com.infodeli.user.login.entity.CodeEmailEntity;
import com.infodeli.user.login.entity.UserEntity;
import com.infodeli.user.login.service.EmailService;
import com.infodeli.user.login.service.UserService;
import org.apache.catalina.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.infodeli.common.utils.PageUtils;
import com.infodeli.common.utils.Query;

import com.infodeli.user.login.dao.UserLocalAuthDao;
import com.infodeli.user.login.entity.UserLocalAuthEntity;
import com.infodeli.user.login.service.UserLocalAuthService;


@Service("userLocalAuthService")
public class UserLocalAuthServiceImpl extends ServiceImpl<UserLocalAuthDao, UserLocalAuthEntity> implements UserLocalAuthService {

    private String AUTH_EMAIL_SUBJECT="校园信息发布平台 邮箱验证";
    private String AUTH_EMAIL_CONTENT="欢迎使用校园信息发布平台，您的验证码是：";

    @Autowired
    EmailService emailService;

    @Autowired
    UserService userService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<UserLocalAuthEntity> page = this.page(
                new Query<UserLocalAuthEntity>().getPage(params),
                new QueryWrapper<UserLocalAuthEntity>()
        );

        return new PageUtils(page);
    }

    @Override // list：根据 uid 获取该用户的所有 本地认证
    public List<UserLocalAuthEntity> listByUid(Long uid) {
        QueryWrapper<UserLocalAuthEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("uid", uid);
        wrapper.eq("show_status", 1);
        List<UserLocalAuthEntity> list = this.list(wrapper);
        Collections.sort(list,(n1,n2)->{
            return (n1.getAuthType() - n2.getAuthType());
        });
        return list;
    }


/*
{
    "uid":,
    "authType":,
    "authContent":,

}
* */
    @Override // getVerifyCode：保存信息，发送验证码
    public void getVerifyCode(UserLocalAuthEntity userLocalAuth) {
        if(userLocalAuth.getAuthType() == LocalAuthEnum.LOCAL_AUTH_PHONE.getAuthType()){
            String veriCode = prepareVerifyCode(userLocalAuth);
            // todo: 发送验证码 给 手机
        }else if(userLocalAuth.getAuthType() == LocalAuthEnum.LOCAL_AUTH_EMAIL.getAuthType()){
            String veriCode = prepareVerifyCode(userLocalAuth);
            // 发送验证码 给 邮箱
            CodeEmailEntity codeEmailEntity = new CodeEmailEntity();
            codeEmailEntity.setTo(userLocalAuth.getAuthContent());
            codeEmailEntity.setSubject(AUTH_EMAIL_SUBJECT);
            codeEmailEntity.setContent(AUTH_EMAIL_CONTENT);
            codeEmailEntity.setCode(veriCode);
            emailService.sendCodeEmail(codeEmailEntity);
        }else{
            throw ServiceExceptionUtils.getServiceException(ExceptionEnum.LOCAL_AUTH_UNKNOWN_TYPE);
        }
    }

    // 准备验证码，保存到数据库
    private String prepareVerifyCode(UserLocalAuthEntity userLocalAuth){
        String veriCode = ComTool.getVeriCode();
        if(userLocalAuth.getAuthType() == LocalAuthEnum.LOCAL_AUTH_PHONE.getAuthType()){
            veriCode = "123456";
        }

        // 考虑：该词条可能存在，所以需要先查一下，看看有没有
        // todo: 绑定时，最好考虑 邮箱、手机号 只能被一人使用，不能多人绑定
        // auth_type、auth_content、show_status
        QueryWrapper<UserLocalAuthEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("uid", userLocalAuth.getUid());
        wrapper.eq("auth_type", userLocalAuth.getAuthType());
        UserLocalAuthEntity one = this.getOne(wrapper);

        if(one == null){ // 不存在，新增
            userLocalAuth.setShowStatus(0);
            userLocalAuth.setVeriCode(veriCode);
            userLocalAuth.setOverTime(ComTool.getVeriCodeDateStr());
            this.save(userLocalAuth);
        }else{ // 存在：修改
            userLocalAuth.setAuthId(one.getAuthId());
            userLocalAuth.setVeriCode(veriCode);
            userLocalAuth.setOverTime(ComTool.getVeriCodeDateStr());
            this.updateById(userLocalAuth);
        }
        return veriCode;
    }

/*
{
    "uid":,
    "authType":,
    "authContent":,
    "veriCode":,
    "showStatus":,
}
* */
    @Override // 区分认证类型，检查验证码，进行绑定or解绑
    public void bindOrUnbind(UserLocalAuthEntity userLocalAuth) {
        if(userLocalAuth.getAuthType() == LocalAuthEnum.LOCAL_AUTH_PHONE.getAuthType()){
            doBindOrUnbind(userLocalAuth);
        }else if(userLocalAuth.getAuthType() == LocalAuthEnum.LOCAL_AUTH_EMAIL.getAuthType()){
            doBindOrUnbind(userLocalAuth);
        }else{
            throw ServiceExceptionUtils.getServiceException(ExceptionEnum.LOCAL_AUTH_UNKNOWN_TYPE);
        }
    }
/*
{
    uid: this.uid,
    authType: this.authObj.authType,
    authContent: this.authObj.authContent,
    veriCode: veriCode,
    // veriCode: 旧密码 or 验证码
}
 */
    @Override // 认证：认证用户的身份
    public void auth(UserLocalAuthEntity userLocalAuth) {
        UserLocalAuthEntity one = null;
        if(userLocalAuth.getAuthType() == 0){ // 进行密码认证
            UserEntity user = new UserEntity();
            user.setUid(userLocalAuth.getUid());
            user.setPassword(ComTool.getMd5Str(userLocalAuth.getVeriCode()));
            userService.authPassword(user);
        }else if(userLocalAuth.getAuthType() == LocalAuthEnum.LOCAL_AUTH_PHONE.getAuthType()){
            one = checkVerifyCode(userLocalAuth);
        }else if(userLocalAuth.getAuthType() == LocalAuthEnum.LOCAL_AUTH_EMAIL.getAuthType()){
            one = checkVerifyCode(userLocalAuth);
        }else {
            throw ServiceExceptionUtils.getServiceException(ExceptionEnum.LOCAL_AUTH_UNKNOWN_TYPE);
        }
        if(userLocalAuth.getAuthType() != 0){ // 清空验证码
            UserLocalAuthEntity updateEntity = new UserLocalAuthEntity();
            updateEntity.setAuthId(one.getAuthId());
            updateEntity.setVeriCode("");
            this.updateById(updateEntity);
        }
    }

    // 检查验证码，进行绑定or解绑
    private void doBindOrUnbind(UserLocalAuthEntity userLocalAuth){
        // 检查验证码
        UserLocalAuthEntity one = checkVerifyCode(userLocalAuth);
        // 验证码通过，修改数据库
        UserLocalAuthEntity updateEntity = new UserLocalAuthEntity();
        updateEntity.setAuthId(one.getAuthId());
        updateEntity.setShowStatus(userLocalAuth.getShowStatus());
        updateEntity.setVeriCode("");
        this.updateById(updateEntity);
    }


    // 检查验证码
    private UserLocalAuthEntity checkVerifyCode(UserLocalAuthEntity userLocalAuth){
        QueryWrapper<UserLocalAuthEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("uid", userLocalAuth.getUid());
        wrapper.eq("auth_type", userLocalAuth.getAuthType());
        wrapper.eq("auth_content", userLocalAuth.getAuthContent());
        UserLocalAuthEntity one = this.getOne(wrapper);
        if(one == null){ // 没找到
            throw ServiceExceptionUtils.getServiceException(ExceptionEnum.LOCAL_AUTH_NOT_EXIST);
        } else if(one.getVeriCode() == null || !one.getVeriCode().equals(userLocalAuth.getVeriCode())){ // 验证码不对
            throw ServiceExceptionUtils.getServiceException(ExceptionEnum.LOCAL_AUTH_VERIFY_CODE_ERROR);
        } else if(one.getOverTime() == null || "".equals(one.getOverTime()) || one.getOverTime().compareTo(ComTool.getDateStr()) < 0){ // 超时了
            throw ServiceExceptionUtils.getServiceException(ExceptionEnum.LOCAL_AUTH_OVERTIME);
        } else { // 正常
            // 返回数据库中的数据
            return one;
        }
    }

}